class TireManageName {
    farsi_name?: string;
    name: string;

    constructor(farsi_name: string = null, name: string = null) {
        this.farsi_name = farsi_name;
        this.name = name;
    }
}

class TireSeller extends TireManageName {
    tire_quantity: number;

    constructor(farsi_name: string = null, name: string = null, tire_quantity: number = null) {
        super(farsi_name, name);
        this.tire_quantity = tire_quantity;
    }
}

class TireBrand extends TireManageName {
    tireSellers: { [key: string]: TireSeller } = {};

    constructor(farsi_name: string = null, name: string = null, tireSellers: TireSeller[] = []) {
        super(farsi_name, name);
        tireSellers.forEach(tireSeller => this.tireSellers[tireSeller.name] = tireSeller)
    }

    setTireSeller(tireSeller: TireSeller) {
        this.tireSellers[tireSeller.name] = tireSeller
    }
}

class TireSize {
    size: string;
    tireBrand: { [key: string]: TireBrand } = {};

    constructor(size: string, tireBrands: TireBrand[] = []) {
        this.size = size;
        tireBrands.forEach(brand => this.tireBrand[brand.name] = brand);
    }
}

class SortedTires {
    sabok: { [key: string]: TireSize } = {};
    sangin: { [key: string]: TireSize } = {};

    constructor(sabok: TireSize[] = [], sangin: TireSize[] = []) {
        sabok.forEach(k => this.sabok[k.size] = k);
        sangin.forEach(k => this.sangin[k.size] = k);
    }
}

interface AvailableTiresInterface {
    added_by: string,
    date_updated: Date,
    id: number
    invoice_number?: string,
    tire_brand: string,
    tire_is_active: number,
    tire_quantity: number,
    tire_seller: string,
    tire_size: string,
    tire_type_is_sabok: number
}

interface incomingTireInfo {
    brand_id: number,
    brands_list_all: {
        [key: string]: {
            farsi_name: string,
            type: {
                sabok?: string[],
                sangin?: string[]
            }
        }
    },
    data: AvailableTiresInterface[],
    form_id: number,
    quantity_id: number,
    seller_id: number,
    sellers_list_all: {
        [key: string]: {
            farsi_name: string,
            tire_type: string[],
            brands: string[],
            address:{htmlcontent:string}
        }
    },
    tire_type_id: number,
    size_id: number,
    seller_address:number,
}

interface GfFieldInterface {
    input: JQuery<HTMLElement>,
    field: JQuery<HTMLElement>
}

class TireInfo {
    public sorted_tires: SortedTires = new SortedTires();
    public incomingTireInfo: incomingTireInfo;
    public elements: {
        tire_type: GfFieldInterface,
        tire_quantity: GfFieldInterface,
        tire_size: GfFieldInterface,
        tire_brand: GfFieldInterface,
        tire_brand_address: GfFieldInterface,
        tire_seller: GfFieldInterface,
    } = {        tire_type:null,
        tire_quantity:null,
        tire_size:null,
        tire_brand:null,
        tire_brand_address:null,
        tire_seller:null    };
    constructor(incomingTireInfo: incomingTireInfo) {
        this.incomingTireInfo = incomingTireInfo;
        incomingTireInfo.data.forEach((data) => {
            const carClass = Number(data.tire_type_is_sabok) === 1 ? 'sabok' : 'sangin';
            const seller = new TireSeller(
                this.incomingTireInfo.sellers_list_all[data.tire_seller].farsi_name,
                data.tire_seller,
                data.tire_quantity
            );
            const brand = new TireBrand(
                this.incomingTireInfo.brands_list_all[data.tire_brand].farsi_name,
                data.tire_brand,
                [seller]);
            if (typeof (this.sorted_tires[carClass][data.tire_size]) === 'undefined') {
                this.sorted_tires[carClass][data.tire_size] = new TireSize(data.tire_size, [brand]);
            }

            if (
                typeof (this.sorted_tires[carClass][data.tire_size]['tireBrand'][data.tire_brand]) === 'undefined'
            ) {
                this.sorted_tires[carClass][data.tire_size]['tireBrand'][data.tire_brand] = brand
            }
            if ((typeof this.sorted_tires[carClass][data.tire_size]['tireBrand'][data.tire_brand]['tireSellers'][data.tire_seller]) === 'undefined') {
                this.sorted_tires[carClass][data.tire_size]['tireBrand'][data.tire_brand]['tireSellers'][data.tire_seller] = seller
            }

        })

        jQuery(document).on('gform_post_render', (event,
                                                  form_id,
                                                  current_page
                                                  )=>this.gFormPostRender(event,form_id,current_page,this));
    }
    public getTireType() {
        const inputs = jQuery('#gform_' + this.incomingTireInfo.form_id).serializeArray();
        return inputs.find(
            input => input.name === 'input_' + this.incomingTireInfo.tire_type_id
        ).value;
    }
    public getTireSize() {
        const inputs = jQuery('#gform_' + this.incomingTireInfo.form_id).serializeArray();
        return inputs.find(input => input.name === 'input_' + this.incomingTireInfo.size_id).value;
    }
    public getTireBrand() {
        const inputs = jQuery('#gform_' + this.incomingTireInfo.form_id).serializeArray();
        const brand_input = inputs.find(input => input.name === 'input_' + this.incomingTireInfo.brand_id)
        if (brand_input === undefined){
            console.error('brand input is undefined');
            return false;
        }
        return brand_input.value;
    }
    public getTireQuantity() {
        const inputs = jQuery('#gform_' + this.incomingTireInfo.form_id).serializeArray();
        return Number(inputs.find(input => input.name === 'input_' + this.incomingTireInfo.quantity_id).value);
    }
    private getElementId(filed_id: number, input = true) {
        const elType: string = input ? 'input' : 'field';
        return jQuery(`#${elType}_${this.incomingTireInfo.form_id}_${filed_id}`);
    }
    private setTireSize(tireinfo:TireInfo=this,event=null){
        const tireSize = this.getTireSize();
        tireinfo.elements.tire_size.input.empty();
        tireinfo.elements.tire_brand.input.empty();
        tireinfo.elements.tire_seller.input.empty();
        const car_type = tireinfo.getTireType();
        const is_sabok = tireinfo.getTireType() === 'sabok' ?1:0;
        const tire_quantity = this.getTireQuantity();
        const sizes_for_quantity:string[] = this.incomingTireInfo.data
            .filter(d=>(Number(d.tire_quantity) >= Number(tire_quantity) && Number(d.tire_type_is_sabok) === is_sabok))
            .map(d=>d.tire_size);
        ;
        const emptyOption=new Option();
        emptyOption.selected=true;
        const size_options:HTMLOptionElement[]  = [emptyOption,... (Object.keys(tireinfo.sorted_tires[car_type])
            .sort()
            .filter(size=>sizes_for_quantity.indexOf(size)>=0)
            .map(size=>{
               const option =  new Option(size)
                 // option.selected = size === tireSize;
               return option;
            }))];
        tireinfo.elements.tire_size.input.append(size_options)
        tireinfo.setTireBrand();
    }
    private setSellersAddress(brand:string,sellers:string[],tireInfo=this){
        const address = `<h6>${brand}</h6> ${sellers
            .map(seller=>tireInfo.incomingTireInfo.sellers_list_all[seller].address.htmlcontent)
            .join('<hr>')}`;
        tireInfo.elements.tire_brand_address.field[0].innerHTML = address
    }
    private setTireBrand(tireinfo:TireInfo=this,event=null){
        tireinfo.elements.tire_brand.input.empty();
        tireinfo.elements.tire_seller.input.empty();
        const car_type = tireinfo.getTireType();
        const tire_size = tireinfo.getTireSize();
        if(tire_size.length === 0 ||tire_size === "" || tire_size === null || typeof (tire_size) === "undefined" ){
           return  tireinfo.setTireSeller()
        }
        const brand_options =  Object.keys(tireinfo.sorted_tires[car_type][tire_size].tireBrand).map(brand=>{
            return new Option(
                tireinfo.sorted_tires[car_type][tire_size]['tireBrand'][brand].farsi_name,
                tireinfo.sorted_tires[car_type][tire_size]['tireBrand'][brand].name,
            )});
        if (brand_options.length > 1) {

             tireinfo.elements.tire_brand.input.append([new Option(),...brand_options]);
        }
        else
        tireinfo.elements.tire_brand.input.append(brand_options);
        tireinfo.setTireSeller()
    }
    private setTireSeller(tireinfo:TireInfo=this,event=null){
        tireinfo.elements.tire_seller.input.empty();
        const car_type = tireinfo.getTireType();
        const tireQuantity = tireinfo.getTireQuantity();
        const tire_size = tireinfo.getTireSize();
        const tire_brand = tireinfo.getTireBrand();
        if(tire_brand === false) return;
        const brand: TireBrand = tireinfo.sorted_tires[car_type][tire_size]['tireBrand'][tire_brand];
        const sellers =  Object.keys(brand['tireSellers'])
            .filter(seller=> Number(brand['tireSellers'][seller].tire_quantity) >=tireQuantity);
        tireinfo.setSellersAddress(brand.farsi_name,sellers);
        const seller_options = sellers
            .map(seller=>{
                return new Option(
                    brand['tireSellers'][seller].farsi_name,
                    brand['tireSellers'][seller].name,
                )});
        if (seller_options.length > 1) {

            return tireinfo.elements.tire_seller.input.append([new Option(),...seller_options]);
        }
        tireinfo.elements.tire_seller.input.append(seller_options);
    }
    private setAllElements() {
        this.elements.tire_type = {input:null,field:null};
        this.elements.tire_quantity = {input:null,field:null};
        this.elements.tire_size = {input:null,field:null};
        this.elements.tire_brand = {input:null,field:null};
        this.elements.tire_brand_address = {input:null,field:null};
        this.elements.tire_seller = {input:null,field:null};
        this.elements.tire_type.input = this.getElementId(this.incomingTireInfo.tire_type_id);
        this.elements.tire_quantity.input = this.getElementId(this.incomingTireInfo.quantity_id);
        this.elements.tire_size.input = this.getElementId(this.incomingTireInfo.size_id);
        this.elements.tire_brand.input = this.getElementId(this.incomingTireInfo.brand_id);
        this.elements.tire_brand_address.input = this.getElementId(this.incomingTireInfo.seller_address);
        this.elements.tire_seller.input = this.getElementId(this.incomingTireInfo.seller_id);
        this.elements.tire_type.field = this.getElementId(this.incomingTireInfo.tire_type_id, false);
        this.elements.tire_quantity.field = this.getElementId(this.incomingTireInfo.quantity_id, false);
        this.elements.tire_size.field = this.getElementId(this.incomingTireInfo.size_id, false);
        this.elements.tire_brand.field = this.getElementId(this.incomingTireInfo.brand_id, false);
        this.elements.tire_brand_address.field = this.getElementId(this.incomingTireInfo.seller_address, false);
        this.elements.tire_seller.field = this.getElementId(this.incomingTireInfo.seller_id, false);
    }
    private gFormPostRender(event,
                            form_id,
                            current_page,
                            tireInfo= this                            ){
        tireInfo.setAllElements();
        tireInfo.initial();    }
    public initial(){
        this.setAllElements();
        this.setTireSize();
        this.setTireBrand();
        this.setTireSeller();
        this.elements.tire_type.input.on("change",(event)=>this.setTireSize(this,event))
        this.elements.tire_quantity.input.on("change",(event)=>this.setTireSize(this,event))
        this.elements.tire_size.input.on("change",(event)=>this.setTireBrand(this,event))
        this.elements.tire_brand.input.on("change",(event)=>this.setTireSeller(this,event))
    }
}
